﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Pvf.Core
{
    internal static class PvfStatics
    {
        /// <summary>
        /// 帕斯卡命名法转下划线驼峰命名法
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string NameCast(string name)
        {
            return System.Text.RegularExpressions.Regex.Replace(name, "([a-z])([A-Z])", "$1 $2").ToLower();
        }

        /// <summary>
        /// 通过名字获取stringTable的key列表
        /// </summary>
        /// <param name="env"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IEnumerable<int> GetStringTableKeys(this IPvfEnv env, string name)
        {
            return env.ReverseStringTable.TryGetValue(name, out var foundLst) ? foundLst : null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="enumType"></param>
        /// <param name="env"></param>
        /// <param name="valueMapper"></param>
        public static void EnumMapSet(Type enumType, IPvfEnv env, Dictionary<int, string> valueMapper)
        {
            var fieldInfos = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (var fieldInfo in fieldInfos)
            {
                if (fieldInfo.GetCustomAttribute<PvfIngoreAttribute>() != null)
                {
                    continue;
                }

                var names = new HashSet<string>();
                var exFieldNamesAttr = fieldInfo.GetCustomAttribute<PvfFieldsAttribute>();
                if (exFieldNamesAttr != null)
                {
                    foreach (var field in exFieldNamesAttr.Fields)
                    {
                        names.Add(field);
                    }
                }
                if (exFieldNamesAttr == null || exFieldNamesAttr.IncludeSourceField)
                {
                    names.Add($"[{NameCast(fieldInfo.Name)}]");
                }

                foreach (var name in names)
                {
                    var tableKeys = env.GetStringTableKeys(name);

                    if (tableKeys != null)
                    {
                        foreach (var key in tableKeys)
                        {
                            valueMapper.Add(key, fieldInfo.Name);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="env"></param>
        /// <param name="baseType"></param>
        /// <param name="fallbackImplType"></param>
        /// <returns></returns>
        public static IDictionary<int, DynamicElementEnumConverterData<TEnum>> BuildDynamicConverter<TEnum>(IPvfEnv env, Type baseType, Type fallbackImplType)
            where TEnum : struct
        {
            var dyMapper = new Dictionary<int, DynamicElementEnumConverterData<TEnum>>();

            var enumFieldInfos = typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public);
            foreach (var enumFieldInfo in enumFieldInfos)
            {
                if (enumFieldInfo.GetCustomAttribute<PvfIngoreAttribute>() != null)
                {
                    continue;
                }

                Type objType = null;
                var defAttr = enumFieldInfo.GetCustomAttribute<PvfDynamicElementMapAttribute>();
                if (defAttr != null)
                {
                    objType = defAttr.ImplType;
                }

                if (objType == null)
                {
                    objType = fallbackImplType;
                }

                if (!baseType.IsAssignableFrom(objType))
                {
                    throw new NotSupportedException($"类{objType.Name}必须继承自{baseType.FullName}");
                }

                var eleConverter = PvfObjectBuilder.Build(objType, env);

                if (eleConverter == null)
                {
                    throw new NotSupportedException($"不支持的类型:{objType.Name}");
                }

                var names = new HashSet<string>();
                var exFieldNamesAttr = enumFieldInfo.GetCustomAttribute<PvfFieldsAttribute>();
                if (exFieldNamesAttr != null)
                {
                    foreach (var field in exFieldNamesAttr.Fields)
                    {
                        names.Add(field);
                    }
                }
                if (exFieldNamesAttr == null || exFieldNamesAttr.IncludeSourceField)
                {
                    names.Add($"[{NameCast(enumFieldInfo.Name)}]");
                }

                foreach (var name in names)
                {
                    var tableKeys = env.GetStringTableKeys(name);

                    if (tableKeys != null)
                    {
                        foreach (var key in tableKeys)
                        {
                            dyMapper.Add(key, new DynamicElementEnumConverterData<TEnum>()
                            {
                                EnumValue = (TEnum)enumFieldInfo.GetRawConstantValue(),
                                Converter = eleConverter
                            });
                        }
                    }
                }
            }

            return dyMapper;
        }
    }
}
